﻿using Google.Apis.Auth.OAuth2;
using Google.Apis.Drive.v2;
using Google.Apis.Drive.v2.Data;
using Google.Apis.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;

namespace WotModSync
{
    public static class GoogleUtils
    {
        public static IList<File> GetFiles(DriveService service, string search)
        {

            IList<File> Files = new List<File>();

            //List all of the files and directories for the current user.  
            // Documentation: https://developers.google.com/drive/v2/reference/files/list
            FilesResource.ListRequest list = service.Files.List();
            list.MaxResults = 1000;
            if (search != null)
            {
                list.Q = search;
            }
            FileList filesFeed = list.Execute();

            //// Loop through until we arrive at an empty page
            while (filesFeed.Items != null)
            {
                // Adding each item  to the list.
                foreach (File item in filesFeed.Items)
                {
                    Files.Add(item);
                }

                // We will know we are on the last page when the next page token is
                // null.
                // If this is the case, break.
                if (filesFeed.NextPageToken == null)
                {
                    break;
                }

                // Prepare the next page of results
                list.PageToken = filesFeed.NextPageToken;

                // Execute and process the next page request
                filesFeed = list.Execute();
            }

            return Files;
        }

        public static File CreateDirectory(DriveService service, string title, string parent, params Property[] properties)
        {

            File NewDirectory = null;

            // Create metaData for a new Directory
            File body = new File();
            body.Title = title;
            body.MimeType = "application/vnd.google-apps.folder";
            body.Parents = new List<ParentReference>() { new ParentReference() { Id = parent } };

            body.Properties = new List<Property>();
            foreach (var property in properties)
            {
                body.Properties.Add(property);
            }

            FilesResource.InsertRequest request = service.Files.Insert(body);
            NewDirectory = request.Execute();


            return NewDirectory;
        }

        public static void DeleteFile(DriveService service, File file)
        {
            FilesResource.DeleteRequest DeleteRequest = service.Files.Delete(file.Id);
            DeleteRequest.Execute();
        }

        public static File UploadFile(DriveService service, string uploadFile, string parent, params Property[] properties)
        {

            if (System.IO.File.Exists(uploadFile))
            {
                File body = new File();
                body.Title = System.IO.Path.GetFileName(uploadFile);
                body.MimeType = GetMimeType(uploadFile);
                body.Parents = new List<ParentReference>() { new ParentReference() { Id = parent } };

                body.Properties = new List<Property>();
                foreach (var property in properties)
                {
                    body.Properties.Add(property);
                }

                // File's content.
                byte[] byteArray = System.IO.File.ReadAllBytes(uploadFile);
                System.IO.MemoryStream stream = new System.IO.MemoryStream(byteArray);

                FilesResource.InsertMediaUpload request = service.Files.Insert(body, stream, GetMimeType(uploadFile));
                request.Upload();
                return request.ResponseBody;
            }
            else
            {
                Console.WriteLine("File does not exist: " + uploadFile);
                return null;
            }

        }

        public static string GetMimeType(string fileName)
        {
            string mimeType = "application/unknown";
            string ext = System.IO.Path.GetExtension(fileName).ToLower();
            Microsoft.Win32.RegistryKey regKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(ext);
            if (regKey != null && regKey.GetValue("Content Type") != null)
                mimeType = regKey.GetValue("Content Type").ToString();
            return mimeType;
        }

        public static DriveService Authenticate()
        {
            //Scopes for use with the Google Drive API
            string[] scopes = new string[] { DriveService.Scope.Drive,
                                 DriveService.Scope.DriveFile};

            var certificate = new X509Certificate2(Properties.Settings.Default.P12File, Properties.Settings.Default.P12FileSecret, X509KeyStorageFlags.Exportable);

            ServiceAccountCredential credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(Properties.Settings.Default.ServiceAccountEmail)
            {

                Scopes = scopes
            }.FromCertificate(certificate));

            DriveService service = new DriveService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = "WotSync",
            });

            return service;
        }

        public static Boolean DownloadFile(DriveService service, File fileResource, string saveTo)
        {

            if (!String.IsNullOrEmpty(fileResource.DownloadUrl))
            {
                var x = service.HttpClient.GetByteArrayAsync(fileResource.DownloadUrl);
                byte[] arrBytes = x.Result;
                System.IO.File.WriteAllBytes(saveTo, arrBytes);
                return true;
            }
            else
            {
                // The file doesn't have any content stored on Drive.
                return false;
            }
        }

        public static File UpdateFile(DriveService service, string uploadFile, string parent, string fileId)
        {

            if (System.IO.File.Exists(uploadFile))
            {
                File body = new File();
                body.Title = System.IO.Path.GetFileName(uploadFile);
                body.MimeType = GetMimeType(uploadFile);
                body.Parents = new List<ParentReference>() { new ParentReference() { Id = parent } };

                // File's content.
                byte[] byteArray = System.IO.File.ReadAllBytes(uploadFile);
                System.IO.MemoryStream stream = new System.IO.MemoryStream(byteArray);

                FilesResource.UpdateMediaUpload request = service.Files.Update(body, fileId, stream, GetMimeType(uploadFile));
                request.Upload();
                return request.ResponseBody;
            }
            else
            {
                Console.WriteLine("File does not exist: " + uploadFile);
                return null;
            }

        }

        public static Property UpdateProperty(DriveService service, String fileId, String key, String newValue, String visibility)
        {

            // First retrieve the property from the API.
            Google.Apis.Drive.v2.PropertiesResource.GetRequest request = service.Properties.Get(fileId, key);
            request.Visibility = visibility;
            Property property = request.Execute();
            property.Value = newValue;

            Google.Apis.Drive.v2.PropertiesResource.UpdateRequest update = service.Properties.Update(property, fileId, key);
            update.Visibility = visibility;
            return update.Execute();

        }

        public static File RenameFile(DriveService service, String fileId, String newTitle)
        {
            File file = new File();
            file.Title = newTitle;

            // Rename the file.
            var patchRequest = service.Files.Patch(file, fileId);
            patchRequest.Fields = "title";

            File updatedFile = patchRequest.Execute();
            return updatedFile;
        }


        public static Permission ShareFile(DriveService service, String fileId, string email, string role)
        {

            Permission newPermission = new Permission();
            newPermission.Value = email;
            newPermission.Type = "user";
            newPermission.Role = role;

            return service.Permissions.Insert(newPermission, fileId).Execute();
        }

        public static IList<Permission> GetPermissionsOnFile(DriveService service, String fileId)
        {
            var permissionList = service.Permissions.List(fileId).Execute();
            return permissionList.Items.Where(pr => pr.EmailAddress != Properties.Settings.Default.ServiceAccountEmail).ToList();

        }

        public static void DeletePermission(DriveService service, String fileId,string permissionId)
        {
            service.Permissions.Delete(fileId, permissionId).Execute();
        }

        

    }
}
